#include <Windows.h>
#include <stdint.h>
#include <stdio.h>
#include <comdef.h>

#include "IHelloWorld.hpp"
#include "CMyComClass.hpp"
#include "DllServer.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction

CMyComClass::CMyComClass() {
    RefCount = 0;
    gdwDllLockCount++;
}

CMyComClass::~CMyComClass() {
    gdwDllLockCount--;
}


//////////////////////////////////////////////////////////////////////
// IUnknown methods

STDMETHODIMP_(ULONG) CMyComClass::AddRef() {
    return ++RefCount;               // Increment this object's reference count.
}

STDMETHODIMP_(ULONG) CMyComClass::Release()
{
    ULONG uRet = --RefCount;             // Decrement this object's reference count.

    if (0 == RefCount)             // Releasing last reference?
        delete this;

    return uRet;
}

STDMETHODIMP CMyComClass::QueryInterface(REFIID riid, void** ppv)
{
    HRESULT hrRet = S_OK;

    OLECHAR* guidString;
    StringFromCLSID(riid, &guidString);

    printf("... CMyComClass::QueryInterface called on IID %ws\r\n", guidString);
    ::CoTaskMemFree(guidString);
    // Check that ppv really points to a void*.

    if (IsBadWritePtr(ppv, sizeof(void*)))
        return E_POINTER;

    // Standard QI initialization - set *ppv to NULL.

    *ppv = NULL;

    // If the client is requesting an interface we support, set *ppv.

    if (InlineIsEqualGUID(riid, IID_IUnknown))
    {
        *ppv = (IUnknown*)this;
    }
    else if (InlineIsEqualGUID(riid, __uuidof(IHelloWorld)))
    {
        *ppv = (IHelloWorld*)this;
        printf("... match for IHelloWorld!\r\n");
    }
    else
    {
        printf("... no matching IID found\r\n");
        hrRet = E_NOINTERFACE;
    }

    // If we're returning an interface pointer, AddRef() it.

    if (S_OK == hrRet)
    {
        printf("... incremented reference count\r\n");
        ((IUnknown*)*ppv)->AddRef();
    }

    return hrRet;
}


//////////////////////////////////////////////////////////////////////
// IHelloWorld methods

STDMETHODIMP CMyComClass::HelloWorld(BSTR bsMessageText) {
    wchar_t SelfPath[MAX_PATH + 1] = { 0 };
    GetModuleFileNameW(nullptr, SelfPath, MAX_PATH + 1);
    MessageBoxW(nullptr, SelfPath, bsMessageText, MB_OK);

    return S_OK;
}
